﻿using System;
using System.Drawing;
using System.Text;
using System.Threading;

namespace Awesom_O_Controller
{
    internal class DiabloHandler : SendMessenger
    {
        private int _clickdelay = 50;
        private int _keydelay = 40;

        public int MinimumGameNameChars = 6;
        public int MaximumGameNameChars = 10;
        public int MinimumGamePassChars = 4;
        public int MaximumGamePassChars = 10;

        public DiabloHandler(IntPtr windowhandle)
            : base(windowhandle)
        {
        }

        public IntPtr WindowHandle
        {
            get { return HWnd; }
            set { HWnd = value; }
        }

        public int ClickDelay
        {
            get { return _clickdelay; }
            set { _clickdelay = value; }
        }

        public int KeyDelay
        {
            get { return _keydelay; }
            set { _keydelay = value; }
        }

        public void Login(string password)
        {
            Thread.Sleep(1000);
            FillText(password);
            SendReturn();
        }

        public void Login(string account, string password)
        {
            Thread.Sleep(2000);
            FillText(password);
            SendTab();
            FillText(account);
            Thread.Sleep(250);
            SendReturn();
        }

        public void SelectChar(int charpos)
        {
            Thread.Sleep(1500);
            DoubleClick(ClickRegion.CharSel[charpos]);
        }

        public void CreateNewChar(string pCharname, int charpos)
        {
            Thread.Sleep(1000);
            Click(ClickRegion.CreateChar);
            Thread.Sleep(2000);
            Click(ClickRegion.SelectZonClass);
            Thread.Sleep(1000);
            if (pCharname != string.Empty)
                FillText(pCharname + RandomString(RandomNumber((MaximumGameNameChars - pCharname.Length - 1), (MaximumGameNameChars - pCharname.Length))));
            else
                FillText(RandomString(RandomNumber(MinimumGameNameChars, MaximumGameNameChars)));
            SendReturn();
        }

        public void JoinChat()
        {
            Click(ClickRegion.EnterChat);
            Thread.Sleep(500);
        }

        public void JoinChannel(string channel)
        {
            Click(ClickRegion.EnterChat);
            Thread.Sleep(500);
            FillText("/j " + channel);
            SendReturn();
        }

        public void ChatChannel(string msg)
        {
            FillText(msg);
            SendReturn();
        }

        public string CreateGame(string gamename, string gamepass, int difficulty)
        {
            Click(ClickRegion.Create);
            Click(ClickRegion.CreateGameName);
            FillText(gamename);
            Click(ClickRegion.CreateGamePass);
            FillText(gamepass);
            Click(ClickRegion.CreateDifficulty[difficulty]);
            Click(ClickRegion.CreateGame);
            return gamename;
        }

        public string CreateRandomGame(int difficulty)
        {
            string gamename = RandomString(RandomNumber(MinimumGameNameChars, MaximumGameNameChars));
            string gamepass = RandomString(RandomNumber(MinimumGamePassChars, MaximumGamePassChars));
            CreateGame(gamename, gamepass, difficulty);
            return gamename;
        }

        public string JoinGame(string gamename, string gamepass)
        {
            Click(ClickRegion.Join);
            Thread.Sleep(500);
            Click(ClickRegion.JoinGameName);
            FillText(gamename);
            Click(ClickRegion.JoinGamePass);
            FillText(gamepass);
            Thread.Sleep(500);
            Click(ClickRegion.JoinGame);
            return gamename;
        }

        public void ChangeDiaWinTitle(string title)
        {
            SendWmText(title);
        }

        public void BringDiaToFront()
        {
            BringAppToFront();
        }

        public void RemoveLoginError()
        {
            Thread.Sleep(500);
            Click(ClickRegion.LoginInvalidInfo);
        }

        #region Private Functions

        private void Click(Region region)
        {
            if (HWnd == IntPtr.Zero) return;
            Point p = region.GetRandomCoordinate();
            SendLeftMouseClick(p.X, p.Y, RandomNumber(_clickdelay, _clickdelay * 2));
        }

        private void DoubleClick(Region region)
        {
            if (HWnd == IntPtr.Zero) return;
            Point p = region.GetRandomCoordinate();
            SendLeftMouseClick(p.X, p.Y, RandomNumber(_clickdelay, _clickdelay * 2));
            SendLeftMouseClick(p.X, p.Y, RandomNumber(_clickdelay, _clickdelay * 2));
        }

        private void SendReturn()
        {
            if (HWnd == IntPtr.Zero) return;
            SendKey(Vk.VkReturn, RandomNumber(_keydelay, _keydelay * 2));
        }

        private void SendTab()
        {
            if (HWnd == IntPtr.Zero) return;
            SendKey(Vk.VkTab, RandomNumber(_keydelay, _keydelay * 2));
        }

        private void FillText(string msg)
        {
            if (HWnd == IntPtr.Zero) return;
            SendText(msg, RandomNumber(_keydelay, _keydelay * 2));
        }

        public string RandomString(int size)
        {
            var builder = new StringBuilder();
            var random = new Random();
            for (int i = 0; i < size; i++)
                builder.Append(Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65))));
            return builder.ToString().ToLower();
        }

        public int RandomNumber(int min, int max)
        {
            return new Random().Next(min, max);
        }

        #endregion
    }

    #region Click Regions

    static class ClickRegion
    {
        public static Region EnterChat = new Region(29, 461, 145, 480, "ENTER_CHAT");
        public static Region Join = new Region(656, 452, 767, 467, "JOIN");
        public static Region Create = new Region(537, 452, 648, 467, "CREATE");
        public static Region Login = new Region(334, 464, 478, 475, "LOGIN");
        public static Region LoginPass = new Region(333, 386, 465, 395, "LOGIN_PASS");
        public static Region LoginAccount = new Region(330, 332, 462, 342, "LOGIN_ACCOUNT");
        public static Region LoginInvalidInfo = new Region(356, 390, 444, 405, "LOGIN_INVALID_INFO");
        public static Region CreateGame = new Region(600, 405, 763, 429, "CREATE_GAME");
        public static Region CreateGamePass = new Region(432, 197, 580, 212, "CREATE_GAME_PASS");
        public static Region CreateGameName = new Region(432, 142, 580, 161, "CREATE_GAME_NAME");
        public static Region ExitGameSafeRegion = new Region(10, 360, 780, 490, "EXIT_GAME_SAFE_REGION");
        public static Region CreateChar = new Region(62, 482, 177, 518, "CREATE_CHARACTER");
        public static Region JoinGame = new Region(600, 405, 763, 429, "JOIN_GAME");
        public static Region JoinGameName = new Region(429, 129, 588, 146, "JOIN_GAME_NAME");
        public static Region JoinGamePass = new Region(604, 129, 735, 140, "JOIN_GAME_PASS");
        public static Region SelectZonClass = new Region(86, 274, 113, 333, "SELECT_ZON_CLASS");

        public static Region[] CreateDifficulty =
        {
            new Region(703, 369, 711, 377, "CREATE_HELL"),
            new Region(560, 369, 568, 377, "CREATE_NIGHTMARE"),
            new Region(434, 369, 442, 377, "CREATE_NORMAL")
        };

        public static Region[] CharSel =
        {
	        new Region(41,92,305,176, "Character_1"),
	        new Region(312,92,576,176, "Character_2"),
	        new Region(41,185,305,269, "Character_3"),
	        new Region(312,185,576,269, "Character_4"),
	        new Region(41,276,305,360, "Character_5"),
	        new Region(312,276,576,360, "Character_6"),
	        new Region(41,370,305,454, "Character_7"),
	        new Region(312,370,576,454, "Character_8")
        };
    }

    class Region
    {
        private readonly int _x1;
        private readonly int _y1;
        private readonly int _x2;
        private readonly int _y2;
        public string Name;

        public Region(int x1, int y1, int x2, int y2, string name)
        {
            _x1 = x1;
            _x2 = x2;
            _y1 = y1;
            _y2 = y2;
            Name = name;
        }

        public Point GetRandomCoordinate()
        {
            var random = new Random();
            int x = random.Next(_x1, _x2);
            int y = random.Next(_y1, _y2);
            return new Point(x, y);
        }
    }

    #endregion
}
